package com.clp.protocol.iec104.server;

import com.clp.protocol.core.common.Checkable;
import com.clp.protocol.core.utils.AssertUtil;
import com.clp.protocol.core.utils.IpUtil;
import lombok.Getter;

@Getter
public class SlaveConfig implements Checkable {
    /**
     * 默认本地ip
     */
    public static final String DEFAULT_LOCAL_HOST = IpUtil.getLocalIpSet().iterator().next();
    /**
     * 默认本地端口号
     */
    public static final int DEFAULT_LOCAL_PORT = 2404;
    /**
     * 默认公共地址
     */
    public static final int DEFAULT_RTU_ADDR = 1;

    private final String localHost;
    private final int localPort;
    private final int rtuAddr;

    // 控制配置
    private final SlaveControlConfig controlConfig;

    // 数据配置
    private final SlaveDataConfig dataConfig;

    protected SlaveConfig(Configurer cfgr) {
        this.localHost = cfgr.localHost;
        this.localPort = cfgr.localPort;
        this.rtuAddr = cfgr.rtuAddr;

        this.controlConfig = cfgr.controlConfig;
        this.dataConfig = cfgr.dataConfig;
    }

    @Override
    public void check() throws Throwable {
        Checker.checkLocalHost(localHost);
        AssertUtil.notNull(controlConfig, "controlConfig");
        controlConfig.check();
        AssertUtil.notNull(dataConfig, "dataConfig");
        dataConfig.check();
    }

    public static Configurer configurer() {
        return new Configurer();
    }

    public static class Configurer {
        private String localHost = DEFAULT_LOCAL_HOST;
        private int localPort = DEFAULT_LOCAL_PORT;
        private int rtuAddr = DEFAULT_RTU_ADDR;

        private SlaveControlConfig controlConfig;
        private SlaveDataConfig dataConfig;

        public Configurer local(int localPort) {
            this.localPort = localPort;
            return this;
        }

        public Configurer local(String localHost, int localPort) {
            AssertUtil.notNull(localHost, "localHost");
            this.localHost = localHost;
            this.localPort = localPort;
            return this;
        }

        public Configurer rtuAddr(int rtuAddr) {
            this.rtuAddr = rtuAddr;
            return this;
        }

        public Configurer controlConfig(SlaveControlConfig controlConfig) {
            this.controlConfig = controlConfig;
            return this;
        }

        public Configurer dataConfig(SlaveDataConfig dataConfig) {
            this.dataConfig = dataConfig;
            return this;
        }

        public SlaveConfig configOk() {
            return new SlaveConfig(this);
        }
    }

    public interface Checker {

        static void checkLocalHost(String localHost) {
            if (!IpUtil.isIpv4(localHost)) {
                throw new IllegalArgumentException(localHost);
            }
        }

    }
}
